package com.trade.dao.impl;

import com.trade.dao.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.apache.commons.dbcp.BasicDataSource;
import org.hibernate.*;
import java.sql.*;
import java.util.*;
import java.io.*;
import java.text.*;
import com.trade.data.*;
import com.trade.data.type.*;

import com.trade.data.calculation.InstrumentTechnicalCalValuesVO;
import com.trade.data.calculation.MACDValuesVO;
import com.trade.data.calculation.MovingAverageValuesVO;
import com.trade.data.calculation.RSIValuesVO;
import com.trade.data.calculation.BollingerBandValuesVO;

import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderErrors;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.compiler.PackageBuilderConfiguration;
import org.drools.io.ResourceFactory;
import org.drools.logger.KnowledgeRuntimeLogger;
import org.drools.logger.KnowledgeRuntimeLoggerFactory;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.builder.conf.*;
import org.drools.runtime.rule.WorkingMemoryEntryPoint;
import org.drools.event.rule.DebugWorkingMemoryEventListener;
import org.drools.event.rule.DebugAgendaEventListener;
import org.drools.runtime.process.ProcessInstance;

//import org.drools.process.core.datatype.impl.type.EnumDataType;

import org.jfree.ui.RefineryUtilities;


public class TestSetupDrools{

	private ApplicationContext context = null;

	private String FILE_PATH = "./temp/ticks/";

	private INSEDataDAO nse = null;

	final IEquityDAO equity ;
	final ILivePriceDAO livePriceDAO;
	static DroolFlowDAO droolFlowDAO;
	final StatefulKnowledgeSession  ksession;

	public TestSetupDrools(){
		context = new ClassPathXmlApplicationContext(
				"applicationContextTest.xml");

		nse = (INSEDataDAO)context.getBean("nseDataDAO");
		equity = (IEquityDAO)context.getBean("equityDAO");
		livePriceDAO = (LivePriceDAO)context.getBean("livePriceDAO");
		droolFlowDAO = (DroolFlowDAO)context.getBean("droolFlowDAO");

		ksession = (StatefulKnowledgeSession)context.getBean("statefulKnowledgeSession");

	}

	public void insertObject(Object object)throws Exception{
		droolFlowDAO.insertObject(object);
	}

	private static DroolFlowDAO getDroolFlowDAO(){
		return droolFlowDAO;
	}


	/**
	* This method load Daily data with 1 Year Period
	*/
	public synchronized void loadInstrumentHistoricalData(String ticker , IntervalTimeTypes intervalTime )throws Exception{

		String fileName = ticker + "_TICKS_" + intervalTime.getName() + ".properties";

		final List<String> tickerList = new ArrayList<String>();
		tickerList.add( ticker );

		System.setOut(new PrintStream( new FileOutputStream( FILE_PATH + ticker + "_TICKS_" + intervalTime.getName() + ".log" ) ));

		System.out.println("Loading file :"+fileName + " , Interval Type : "+ intervalTime);

		Scanner input = new Scanner( new FileInputStream( FILE_PATH + fileName));

		try{
				while( input.hasNextLine()){

					Thread.sleep(20);

					String data[] = input.nextLine().split(",");

					HistoricalDataVO histDataVO = new EquityIntradayDataVO();
					histDataVO.setSymbol( ticker );
					histDataVO.setDate(new java.util.Date());
					histDataVO.setClose(Double.parseDouble(data[1]));
					histDataVO.setHigh(Double.parseDouble(data[2]) );
					histDataVO.setLow(Double.parseDouble(data[3]));
					histDataVO.setOpen(Double.parseDouble(data[4]));
					histDataVO.setVolume(Double.parseDouble(data[5]));
					histDataVO.setIntervalTimeTypes( intervalTime );

					if( histDataVO.getClose().doubleValue() == histDataVO.getHigh().doubleValue()
						&&
						histDataVO.getClose().doubleValue() == histDataVO.getLow().doubleValue()
						&&
						histDataVO.getClose().doubleValue() == histDataVO.getOpen().doubleValue()

						){
						System.out.println("Skip Data close - "+ histDataVO.getClose() + ", high - "
							+ histDataVO.getHigh());
						continue;
					}

					System.out.println(""+histDataVO);

					droolFlowDAO.insertObject(histDataVO,intervalTime );
					ProcessFilterVO processFilterVO = new ProcessFilterVO();
					processFilterVO.setSymbol( histDataVO.getSymbol() );
					processFilterVO.setHistoricalDataVO( histDataVO );
					processFilterVO.setIntervalTimeTypes( intervalTime );
					ProcessInstance processInstance = droolFlowDAO.startTradeFlowProcess(processFilterVO);
					droolFlowDAO.fireAllRules();


					//For 2 Min , 30 Min also inserted in 3 Second working memory to calculate signal.

					if( IntervalTimeTypes.T2_MIN.getId() == intervalTime.getId()
						||
						IntervalTimeTypes.T30_MIN.getId() == intervalTime.getId()
					){
						HistoricalDataVO historicalDataVO = new EquityIntradayDataVO();
						historicalDataVO.setSymbol( ticker );
						historicalDataVO.setDate(new java.util.Date());
						historicalDataVO.setClose(Double.parseDouble(data[1]));
						historicalDataVO.setHigh(Double.parseDouble(data[2]) );
						historicalDataVO.setLow(Double.parseDouble(data[3]));
						historicalDataVO.setOpen(Double.parseDouble(data[4]));
						historicalDataVO.setVolume(Double.parseDouble(data[5]));
						historicalDataVO.setIntervalTimeTypes(IntervalTimeTypes.T3_SEC);

						droolFlowDAO.insertObject(historicalDataVO,IntervalTimeTypes.T3_SEC);

						ProcessFilterVO processFilterVOTemp = new ProcessFilterVO();
						processFilterVOTemp.setSymbol( historicalDataVO.getSymbol() );
						processFilterVOTemp.setHistoricalDataVO( historicalDataVO );
						processFilterVOTemp.setIntervalTimeTypes( IntervalTimeTypes.T3_SEC );
						droolFlowDAO.startTradeFlowProcess(processFilterVOTemp);
						droolFlowDAO.fireAllRules();
					}


				}
		}catch(Exception e){
			System.out.println("Error - "+e.getLocalizedMessage());
		}
	}



	/**
	* This method load LIVE prices for Ticker and period
	*/
	public synchronized void loadInstrumentLiveData( final List<String> tickerList , final IntervalTimeTypes intervalTime )throws Exception{

		HistoricalDataFilterVO historicalDataFilterVO = new HistoricalDataFilterVO();
		historicalDataFilterVO.setTickerList(tickerList);
		historicalDataFilterVO.setInterval(intervalTime );

		System.setOut(new PrintStream( new FileOutputStream( FILE_PATH + "LIVE_TICKS_" + intervalTime.getName() + ".log" ) ));
		//System.setOut(new PrintStream( System.out ));

		try{

			List<HistoricalDataVO> histList = livePriceDAO.getClosePrices(historicalDataFilterVO );

			for(HistoricalDataVO histDataVO :  histList){


					if( histDataVO.getClose().doubleValue() == histDataVO.getHigh().doubleValue()
						&&
						histDataVO.getClose().doubleValue() == histDataVO.getLow().doubleValue()
						&&
						histDataVO.getClose().doubleValue() == histDataVO.getOpen().doubleValue()

						){
						System.out.println("Skip Data close - "+ histDataVO.getClose() + ", high - "
							+ histDataVO.getHigh());
						continue;
					}


					histDataVO.setIntervalTimeTypes(intervalTime );

					droolFlowDAO.insertObject(histDataVO, intervalTime);
					ProcessFilterVO processFilterVO = new ProcessFilterVO();
					processFilterVO.setSymbol( histDataVO.getSymbol() );
					processFilterVO.setHistoricalDataVO( histDataVO );
					processFilterVO.setIntervalTimeTypes( intervalTime );
					ProcessInstance processInstance = droolFlowDAO.startTradeFlowProcess(processFilterVO);
					droolFlowDAO.fireAllRules();
			}
		}catch(Exception e){
			System.out.println(e.getLocalizedMessage());
		}

		new Thread(new Runnable() {

			@Override
			public void run() {
				System.out.println("\n\n\n"+ intervalTime +" Live Price Thread started\n\n\n");
				while(true){
					try{
						Thread.sleep( intervalTime.getPeriodValue() * 1000 );

						HistoricalDataFilterVO historicalDataFilterVO = new HistoricalDataFilterVO();
						historicalDataFilterVO.setTickerList(tickerList);

						if( IntervalTimeTypes.T2_MIN.getId() == intervalTime.getId()){
							historicalDataFilterVO.setInterval(IntervalTimeTypes.T2_MIN_1DAY);
						}
						else if(IntervalTimeTypes.T30_MIN.getId() == intervalTime.getId()){
							historicalDataFilterVO.setInterval(IntervalTimeTypes.T30_MIN_1DAY);
						}
						else{
							historicalDataFilterVO.setInterval(intervalTime);
						}
						List<HistoricalDataVO> histList = livePriceDAO.getIntradayClosePrices(historicalDataFilterVO );

						for(HistoricalDataVO histDataVO :  histList){

							if( histDataVO.getClose().doubleValue() == histDataVO.getHigh().doubleValue()
								&&
								histDataVO.getClose().doubleValue() == histDataVO.getLow().doubleValue()
								&&
								histDataVO.getClose().doubleValue() == histDataVO.getOpen().doubleValue()

								){
								System.out.println("Skip Data close - "+ histDataVO.getClose() + ", high - "
									+ histDataVO.getHigh());
								continue;
							}

							histDataVO.setIntervalTimeTypes(intervalTime);
							droolFlowDAO.insertObject(histDataVO,intervalTime);

							ProcessFilterVO processFilterVO = new ProcessFilterVO();
							processFilterVO.setSymbol( histDataVO.getSymbol() );
							processFilterVO.setHistoricalDataVO( histDataVO );
							processFilterVO.setIntervalTimeTypes( intervalTime );
							droolFlowDAO.startTradeFlowProcess(processFilterVO);
							droolFlowDAO.fireAllRules();

							//For 2 Min , 30 Min also inserted in 3 Second working memory to calcualte signal.

							if( IntervalTimeTypes.T2_MIN.getId() == intervalTime.getId()
								||
								IntervalTimeTypes.T30_MIN.getId() == intervalTime.getId()
							){
								HistoricalDataVO historicalDataVO = new EquityIntradayDataVO();
								historicalDataVO.setSymbol( histDataVO.getSymbol()  );
								historicalDataVO.setDate(new java.util.Date());
								historicalDataVO.setClose(histDataVO.getClose());
								historicalDataVO.setHigh( histDataVO.getHigh() );
								historicalDataVO.setLow( histDataVO.getLow());
								historicalDataVO.setOpen( histDataVO.getOpen() );
								historicalDataVO.setVolume( histDataVO.getVolume());
								historicalDataVO.setIntervalTimeTypes(IntervalTimeTypes.T3_SEC);

								droolFlowDAO.insertObject(historicalDataVO,IntervalTimeTypes.T3_SEC);

								ProcessFilterVO processFilterVOTemp = new ProcessFilterVO();
								processFilterVOTemp.setSymbol( historicalDataVO.getSymbol() );
								processFilterVOTemp.setHistoricalDataVO( historicalDataVO );
								processFilterVOTemp.setIntervalTimeTypes( IntervalTimeTypes.T3_SEC );
								droolFlowDAO.startTradeFlowProcess(processFilterVOTemp);
								droolFlowDAO.fireAllRules();
							}

						}

						System.out.println("");

					}catch(Exception e){
						System.out.println(e.getLocalizedMessage());
					}finally{
					}
				}
			}
		}).start();


	}


	public static void main(String[] args)throws Exception {


		System.setProperty("drools.ruleflow.port", "true");

		final TestSetupDrools test = new TestSetupDrools();


		final List<String> tickerList = new ArrayList<String>();
		tickerList.add("NIFTY");
		//tickerList.add("SBIN");
		//tickerList.add("BHEL");
		//tickerList.add("RANBAXY");
		//tickerList.add("HINDALCO");
		//tickerList.add("INFOSYS");
		//tickerList.add("COAL");
		//tickerList.add("TATASTEEL");


		for(final String ticker : tickerList ){

			InstrumentVO instrumentVO =new InstrumentVO();
			instrumentVO.setSecurityName( ticker );
			instrumentVO.setMarketType("");
			instrumentVO.setSymbol( ticker );

			test.insertObject(instrumentVO);

			//Thread for 1 Year data processing

			new Thread(new Runnable() {

				@Override
				public void run() {
					System.out.println("Load 1 YEAR "+ ticker +" data thread started \n\n\n");
					try{
						test.loadInstrumentHistoricalData( ticker , IntervalTimeTypes.T1_YEAR);
					}catch(Exception e){
						System.out.println("Load 1 YEAR "+ ticker +" data thread error " + e.getMessage());
					}
				}
			}).start();

			Thread.sleep(2 * 1000);

			//Thread for Weekly data processing

			new Thread(new Runnable() {

				@Override
				public void run() {
					System.out.println("Load 1 WEEK "+ ticker +" data thread started \n\n\n");
					try{
						test.loadInstrumentHistoricalData( ticker , IntervalTimeTypes.TWEEK_DAY);
					}catch(Exception e){
						System.out.println("Load 1 WEEK "+ ticker +" data thread error " + e.getMessage());
					}
				}
			}).start();

			Thread.sleep(15 * 1000);

			//Thread for 30 Min data processing

			new Thread(new Runnable() {

				@Override
				public void run() {
					System.out.println("Load 30 Min "+ ticker +" data thread started \n\n\n");
					try{
						test.loadInstrumentHistoricalData( ticker , IntervalTimeTypes.T30_MIN);
					}catch(Exception e){
						System.out.println("Load 1 WEEK "+ ticker +" data thread error " + e.getMessage());
					}
				}
			}).start();

		}

		Thread.sleep(10 * 1000);


		//Dummy thread for testing
		/*for(final String ticker : tickerList ){
			new Thread(new Runnable() {

				@Override
				public void run() {
					System.out.println("Load 3 Sec "+ ticker +" data thread started \n\n\n");
					try{
						test.loadInstrumentHistoricalData( ticker , IntervalTimeTypes.T3_SEC);
					}catch(Exception e){
						System.out.println("Load 3 Sec "+ ticker +" data thread error " + e.getMessage());
					}
				}
			}).start();
		}*/


		//test.loadInstrumentLiveData(tickerList , IntervalTimeTypes.T3_SEC);

		//test.loadInstrumentLiveData(tickerList , IntervalTimeTypes.T2_MIN);

		//test.loadInstrumentLiveData(tickerList , IntervalTimeTypes.T30_MIN);


		//Chart demo

		System.setOut(new PrintStream( System.out ));

		System.out.println("Load chart started");

		final JFreeChartDemo demo = new JFreeChartDemo(getDroolFlowDAO());
		demo.draw30MinChart("NIFTY",IntervalTimeTypes.T1_YEAR);
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        demo.setVisible(true);

        System.out.println("Chart visible");

        Thread.sleep(15 * 1000);

	}

}